package drunken

import (
	"github.com/akirakazu/go-simplejson"
	"net"
	"os"
	"regexp"
	"strings"
	"time"
)

type Broadcaster struct {
	ip string
	addr *net.UDPAddr
	conn *net.UDPConn
}

func NewBroadcaster() *Broadcaster {
	u := new(Broadcaster)
	u.ip = ""
	return u
}

func (u *Broadcaster) start() {
	go func() {
		for {
			s := u.grabIp()
			if s {
				time.Sleep(20 * time.Second)
			} else {
				time.Sleep(time.Second)
			}
		}
	}
}

func (u *Broadcaster) grabIp() bool {
	ip := u.getLocalAddr()
	if ip != "" {
		u.ip = ip
		return true
	} else {
		return false
	}
}

func (u *Broadcaster) sendUri() {
	if u.addr == nil {
		addr, err := net.ResolveUDPAddr("udp", "224.1.2.3:60008")
		if err != nil {
			return
		}
		u.addr = addr
	}

	if u.conn == nil {
		conn, error := net.ListenerMulticastUDP("udp", nil, u.addr)
		if err != nil {
			return
		}
		u.conn = conn
	}
	
	pack := json.New()
	pack.Set("ip", u.ip)
	name, _ := os.Hostname()
	pack.Set("name", name)

	// deprecated

	/* two different kine of type: online and change
	 {
		type: "online",
		ip: "192.168.10.158",
		name: "AKI-THINK"
	 }

	 {
		type: "change",
		ip: "192.168.10.158",
		name: "AKI-THINK",
		content: {
			type: "clipboard", // or file
			body: "abcdefg" // or null
		}
	 }
	 */
	pack.Set("type", "online")

	b, _ := pack.MarshalJSON()
	u.conn.SetDeadline(time.Now().Add(time.Second * 10))
	_, err := u.conn.WriteToUDP(b, u.addr)
	if err != nil {
		u.conn = nil
	}
}

func (u *Broadcaster) getLocalAddr() string {
	ipPattern := "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
		"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
		"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
		"([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"
	addrs, _ := net.InterfaceAddrs()
	for _, addr := range addrs {
		s := strings.Split(addr.String(), "/")[0]
		if s != "127.0.0.1" && s != "0.0.0.0" {
			matched, _ := regexp.MatchString(ipPattern, s)
			if matched {
				return s
			}
		}
	}
	return ""
}